# coding=utf-8

import time
import os
from django.conf import settings
from django.db import models
from django.utils import timezone
from apps.WechatTp.models import WechatTp
from utils.wx.wechat import WeChat
from utils.exceptions import CustomError
from utils.file_operation import CertPath
# from apps.tenant.models import Tenant


class WechatApplet(models.Model):
    AUDIT_SUCCESS = 0
    AUDIT_REJECT = 1
    AUDITING = 2
    RECALL = 3
    AUDIT_DELAY = 4

    AUDIT_STATUS_CHOICE = (
        (AUDIT_SUCCESS, u'审核通过'),
        (AUDIT_REJECT, u'审核拒绝'),
        (AUDITING, u'审核中'),
        (RECALL, u'已撤回'),
        (AUDIT_DELAY, u'审核延后'),
    )

    # tenant = models.ForeignKey(Tenant, verbose_name=u'租户', on_delete=models.PROTECT, editable=False)
    wechat_tp = models.ForeignKey(WechatTp, verbose_name=u'第三方平台', on_delete=models.PROTECT, editable=False)
    authorizer_appid = models.CharField(max_length=512, verbose_name=u'授权方appid')
    secret = models.CharField(max_length=512, verbose_name=u'小程序秘钥', null=True)
    authorizer_refresh_token = models.CharField(max_length=512, verbose_name=u'刷新令牌')
    authorizer_access_token = models.CharField(max_length=512, verbose_name=u'令牌')
    access_token_gtime = models.DateTimeField(verbose_name=u"获取令牌时间")
    expires_in = models.IntegerField(verbose_name=u'令牌有效期')
    is_authorize = models.BooleanField(verbose_name=u'是否授权', default=False)
    message_template_id = models.CharField(max_length=255, verbose_name=u'消息模版ID', null=True)

    nick_name = models.CharField(max_length=255, verbose_name=u'昵称', default="")
    head_img = models.CharField(max_length=255, verbose_name=u'头像', default="")
    principal_name = models.CharField(max_length=255, verbose_name=u'主体名称', default="")
    qrcode_url = models.CharField(max_length=512, verbose_name=u'二维码', default="")
    user_version = models.CharField(max_length=512, verbose_name=u'当前程序版本', default="")
    template_id = models.CharField(max_length=512, verbose_name=u'当前模板', default="")
    tenant_num = models.CharField(max_length=512, verbose_name=u'商户号', default="")
    tenant_key = models.CharField(max_length=512, verbose_name=u'商户密钥', default="")

    apiclient_cert = models.CharField(max_length=255, verbose_name=u'API证书cert', default="")
    apiclient_key = models.CharField(max_length=255, verbose_name=u'API证书key', default="")

    auditid = models.CharField(max_length=512, verbose_name=u'待审核ID', default="")
    wait_audit_version = models.CharField(max_length=512, verbose_name=u'待审核版本', null=True)
    wait_audit_template = models.CharField(max_length=512, verbose_name=u'待审核模板', null=True)
    audit_status = models.IntegerField(choices=AUDIT_STATUS_CHOICE, verbose_name=u'审核状态', null=True)
    reject_reason = models.CharField(max_length=512, verbose_name=u'拒绝原因', default="")

    class Meta:
        db_table = "wechat_applet"
        ordering = ['-id']
        index_together = ()
        verbose_name = u"小程序"
        default_permissions = ()

    @staticmethod
    def getById(id):
        try:
            id = int(id)
        except:
            raise CustomError(u'无效的小程序ID！')

        instance = WechatApplet.objects.filter(pk=id).first()
        if not instance:
            raise CustomError(u'未找到相应的小程序！')
        return instance

    @staticmethod
    def getByAppid(appid):
        instance = WechatApplet.objects.filter(authorizer_appid=appid).first()
        if not instance:
            raise CustomError(u'未找到相应的小程序！')
        return instance

    @staticmethod
    def addAuthorizer(wechat_component, authorization_code, tenant):
        gtime = timezone.now()
        component_appid = wechat_component.getAppid()
        component_access_token = wechat_component.getAccessToken()
        res = WeChat.getAuthorizationInfo(component_appid, authorization_code, component_access_token)
        ares = WeChat.getAuthorizerInfo(component_appid, res['authorization_info']['authorizer_appid'], component_access_token)
        authorizer = WechatApplet.getByAppidAndComponentAppid(res['authorization_info']['authorizer_appid'], component_appid)
        if authorizer:
            if authorizer.is_authorize:
                raise CustomError(u'该小程序已授权！')
            authorizer.refresh(res['authorization_info'], ares['authorizer_info'], gtime, tenant)
        else:
            authorizer = WechatApplet.objects.create(
                # tenant=tenant,
                wechat_tp=wechat_component,
                authorizer_appid=res['authorization_info']['authorizer_appid'],
                authorizer_refresh_token=res['authorization_info']['authorizer_refresh_token'],
                authorizer_access_token=res['authorization_info']['authorizer_access_token'],
                access_token_gtime=gtime,
                expires_in=res['authorization_info']['expires_in'],
                principal_name=ares['authorizer_info']['principal_name'],
                nick_name=ares['authorizer_info']['nick_name'],
                head_img=ares['authorizer_info']['head_img'],
                qrcode_url=ares['authorizer_info']['qrcode_url'],
                is_authorize=True
            )
        # 设置服务器域名
        authorizer.setDomain()
        return authorizer

    @staticmethod
    def getByAppidAndComponentAppid(appid, component_appid):
        authorizer = WechatApplet.objects.filter(authorizer_appid=appid, wechat_tp_id__component_appid=component_appid).first()
        return authorizer

    def getComponent(self):
        return self.wechat_tp

    def getAccessToken(self):
        if self.authorizer_access_token:
            last_time = time.mktime(self.access_token_gtime.timetuple()) + self.expires_in
            now = time.mktime(timezone.now().timetuple())
            if last_time > now:
                return self.authorizer_access_token
        if not self.authorizer_refresh_token:
            return ''
        gtime = timezone.now()
        component = self.getComponent()
        res = WeChat.getAuthorizerAccessToken(component.getAppid(), self.authorizer_appid, self.authorizer_refresh_token, component.getAccessToken())
        self.refreshAccessToken(gtime, res['authorizer_access_token'], res['expires_in'], res['authorizer_refresh_token'])
        return self.authorizer_access_token

    def revoke(self):
        # tenant = self.tenant
        # tenant.is_bind_app = False
        # tenant.save()
        self.is_authorize = False
        self.save()

    def refreshAccessToken(self, gtime, access_token, expires_in, refresh_token):
        self.authorizer_access_token = access_token
        self.access_token_gtime = gtime
        self.expires_in = expires_in
        self.authorizer_refresh_token = refresh_token
        self.save()

    def refresh(self, authorization_info, authorizer_info, access_token_gtime, tenant):
        self.authorizer_refresh_token = authorization_info['authorizer_refresh_token']
        self.authorizer_access_token = authorization_info['authorizer_access_token']
        self.access_token_gtime = access_token_gtime
        self.expires_in = authorization_info['expires_in']
        self.principal_name = authorizer_info['principal_name']
        self.nick_name = authorizer_info['nick_name']
        self.head_img = authorizer_info['head_img']
        self.qrcode_url = authorizer_info['qrcode_url']
        self.is_authorize = True
        # self.tenant = tenant
        self.save()

    def uploadCode(self, template_id, user_version, user_desc):
        WeChat.commitCode(self.getAccessToken(), template_id, user_version, user_desc)
        result = WeChat.submitAuditCode(self.getAccessToken())
        self.auditid = result['auditid']
        self.wait_audit_version = user_version
        self.wait_audit_template = template_id
        self.audit_status = WechatApplet.AUDITING
        self.reject_reason = ''
        self.save()

    def refreshAuditStatus(self):
        result = WeChat.getLastSubmitAuditCodeStatus(self.getAccessToken())
        if self.auditid == str(result['auditid']):
            if result['status'] == WechatApplet.AUDIT_SUCCESS:
                self.weapp_audit_success()
            elif result['status'] == WechatApplet.AUDIT_REJECT:
                self.weapp_audit_fail(result['reason'])
            elif result['status'] == WechatApplet.RECALL:
                self.weapp_audit_recall()
            elif result['status'] == WechatApplet.AUDIT_DELAY:
                self.weapp_audit_delay(result['reason'])

    def weapp_audit_recall(self):
        self.auditid = ''
        self.wait_audit_template = None
        self.wait_audit_version = None
        self.audit_status = None
        self.reject_reason = ''
        self.save()

    def weapp_audit_success(self):
        self.user_version = self.wait_audit_version
        self.template_id = self.wait_audit_template
        self.auditid = ''
        self.wait_audit_template = None
        self.wait_audit_version = None
        self.audit_status = None
        self.reject_reason = ''
        self.save()

    def weapp_audit_fail(self, reason):
        self.audit_status = WechatApplet.AUDIT_REJECT
        self.reject_reason = reason
        self.save()

    def weapp_audit_delay(self, reason):
        self.audit_status = WechatApplet.AUDIT_DELAY
        self.reject_reason = reason
        self.save()

    def setDomain(self):
        requestdomain = uploaddomain = downloaddomain = ['https://xapp.aiche360.cn', ]
        wsrequestdomain = []
        WeChat.modify_domain(self.getAccessToken(), 'set', requestdomain, wsrequestdomain, uploaddomain, downloaddomain)

    def addPlugin(self):
        result = WeChat.addPlugin(self.getAccessToken())
        return result

    def releaseApplet(self):
        result = WeChat.releaseCode(self.getAccessToken())
        return result

    def getMsgTemplateId(self):
        if self.message_template_id:
            return self.message_template_id
        templates = WeChat.getTemplateList(self.getAccessToken())
        for template in templates:
            if template['title'] == u'未读私信通知':
                self.message_template_id = template['priTmplId']
                self.save()
                return template['priTmplId']
        return ''

    def sendMsg(self, msg, openid):
        template_id = self.getMsgTemplateId()
        if not template_id:
            return
        time = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
        data = {'thing6':{'value':msg},'time7':{'value': time}}
        page = '/pages/message_list/message_list'
        WeChat.sendSubscribeMessage(self.getAccessToken(), openid, template_id, page, data)

    def upload_cert_file(self, file):
        path = 'zzly_xcx_cert/%d/' % self.id
        upload_path = CertPath(path)
        filename = '%s%s' % (upload_path.path, file.name)
        full_filename = "%s/%s" % (settings.MEDIA_ROOT, filename)
        with open(full_filename, 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)
        if file.name == 'apiclient_cert.pem':
            self.apiclient_cert = full_filename
        elif file.name == 'apiclient_key.pem':
            self.apiclient_key = full_filename
        self.save()
